using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using SheLife.Domain.Entities;
using SheLife.Domain.Interfaces;

namespace SheLife.Infrastructure.Repositories
{
    public class SkincareProductRepository : ISkincareProductRepository
    {
        private readonly SheLifeDbContext _context;

        public SkincareProductRepository(SheLifeDbContext context)
        {
            _context = context;
        }

        public async Task<SkincareProduct> GetByIdAsync(int id)
        {
            return await _context.SkincareProducts.FindAsync(id);
        }

        public async Task<IEnumerable<SkincareProduct>> GetByUserIdAsync(int userId)
        {
            return await _context.SkincareProducts
                .Include(p => p.Product)
                .Where(p => p.UserId == userId)
                .OrderByDescending(p => p.CreatedAt)
                .ToListAsync();
        }

        public async Task<IEnumerable<SkincareProduct>> GetByUserIdAndCategoryAsync(int userId, string category)
        {
            return await _context.SkincareProducts
                .Include(p => p.Product)
                .Where(p => p.UserId == userId && p.Category == category)
                .OrderByDescending(p => p.CreatedAt)
                .ToListAsync();
        }

        public async Task<IEnumerable<SkincareProduct>> GetLowStockProductsAsync(int userId)
        {
            return await _context.SkincareProducts
                .Include(p => p.Product)
                .Where(p => p.UserId == userId && p.StockQuantity <= p.LowStockThreshold)
                .OrderBy(p => p.StockQuantity)
                .ToListAsync();
        }

        public async Task<IEnumerable<SkincareProduct>> GetExpiringProductsAsync(int userId, int daysAhead = 30)
        {
            var futureDate = DateTime.Today.AddDays(daysAhead);
            return await _context.SkincareProducts
                .Include(p => p.Product)
                .Where(p => p.UserId == userId && 
                           p.ExpiryDate.HasValue && 
                           p.ExpiryDate.Value <= futureDate)
                .OrderBy(p => p.ExpiryDate)
                .ToListAsync();
        }

        public async Task<SkincareProduct> AddAsync(SkincareProduct product)
        {
            product.CreatedAt = DateTime.UtcNow;
            await _context.SkincareProducts.AddAsync(product);
            await _context.SaveChangesAsync();
            return product;
        }

        public async Task UpdateAsync(SkincareProduct product)
        {
            product.UpdatedAt = DateTime.UtcNow;
            _context.Entry(product).State = EntityState.Modified;
            await _context.SaveChangesAsync();
        }

        public async Task DeleteAsync(int id)
        {
            var product = await GetByIdAsync(id);
            if (product != null)
            {
                _context.SkincareProducts.Remove(product);
                await _context.SaveChangesAsync();
            }
        }

        public async Task<bool> ExistsAsync(int id)
        {
            return await _context.SkincareProducts.AnyAsync(p => p.Id == id);
        }

        public async Task<Dictionary<string, int>> GetCategoryStatsAsync(int userId)
        {
            return await _context.SkincareProducts
                .Where(p => p.UserId == userId)
                .GroupBy(p => p.Category)
                .Select(g => new { Category = g.Key, Count = g.Count() })
                .ToDictionaryAsync(g => g.Category, g => g.Count);
        }

        public async Task<int> GetTotalProductCountAsync(int userId)
        {
            return await _context.SkincareProducts
                .CountAsync(p => p.UserId == userId);
        }

        public async Task UpdateStockAsync(int id, int quantity)
        {
            var product = await GetByIdAsync(id);
            if (product != null)
            {
                product.StockQuantity = quantity;
                product.UpdatedAt = DateTime.UtcNow;
                await _context.SaveChangesAsync();
            }
        }
    }
}